package com.aaron.crowd.mvc.config;

import com.aaron.crowd.constant.CrowdConstant;
import com.aaron.crowd.exception.LoginAcctAlreadyInUseException;
import com.aaron.crowd.exception.LoginFailedException;
import com.aaron.crowd.util.CrowdUtil;
import com.aaron.crowd.util.ResultEntity;
import com.aaron.crowd.mvc.handler.TestHandler;
import com.google.gson.Gson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @BelongsProject: atcrowdfuncding
 * @BelongsPackage: com.aaron.crowd.mvc.config
 * @author: Andy
 * @date: 2021.3.26 19:07
 * @Description:
 * @since JDK 1.8
 */
/*@ControllerAdvice表示当前类是一个基于注解的异常处理类*/
@EnableWebMvc
@ControllerAdvice
public class CrowdExceptionResolver {
    private Logger logger = LoggerFactory.getLogger(TestHandler.class);

    /**
     * 用户添加时用户名重复
     * @param exception 异常类型
     * @param request   页面信息
     * @param response  响应体
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = LoginAcctAlreadyInUseException.class)
    public ModelAndView LoginAcctAlreadyInUseException(
            /*实际捕获到的异常类型*/
            LoginAcctAlreadyInUseException exception,
            /*当前请求的对象*/
            HttpServletRequest request,
            /*当前响应的对象*/
            HttpServletResponse response) throws IOException {
        String viewName = "admin-add";
        return this.commonResolve(viewName,exception,request,response);
    }

    /**
     * 违反约束抛此异常
     * @param exception
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = DuplicateKeyException.class)
    public ModelAndView DuplicateKeyException(
            /*实际捕获到的异常类型*/
            DuplicateKeyException exception,
            /*当前请求的对象*/
            HttpServletRequest request,
            /*当前响应的对象*/
            HttpServletResponse response) throws IOException {
        String viewName = "system-error";
        return this.commonResolve(viewName,exception,request,response);
    }
    /**
     * @ExceptionHandler  将一个具体的异常和方法关联起来
     * */
    @ExceptionHandler(value = NullPointerException.class)
    public ModelAndView resolveNullPointerException(
            /*实际捕获到的异常类型*/
            NullPointerException exception,
            /*当前请求的对象*/
            HttpServletRequest request,
            /*当前响应的对象*/
            HttpServletResponse response) throws IOException {
        String viewName = "system-error";
        return this.commonResolve(viewName,exception,request,response);
    }

    @ExceptionHandler(value = ArithmeticException.class)
    public ModelAndView resolveArithmeticException(
            /*实际捕获到的异常类型*/
            ArithmeticException exception,
            /*当前请求的对象*/
            HttpServletRequest request,
            /*当前响应的对象*/
            HttpServletResponse response) throws IOException {
        String viewName = "system-error";
        return this.commonResolve(viewName,exception,request,response);
    }

    /**
     * 登录异常
     * @param exception
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = LoginFailedException.class)
    public ModelAndView resolveLoginFailedException(
            /*实际捕获到的异常类型*/
            LoginFailedException exception,
            /*当前请求的对象*/
            HttpServletRequest request,
            /*当前响应的对象*/
            HttpServletResponse response) throws IOException {
        String viewName = "admin-login";
        return this.commonResolve(viewName,exception,request,response);
    }

    /**
     * @ExceptionHandler：将一个具体的异常和方法关联起来
     */
    private ModelAndView commonResolve(
            /*显示异常的页面*/
            String viewName,
            /*实际捕获到的异常类型*/
            Exception exception,
            /*当前请求的对象*/
            HttpServletRequest request,
            /*当前响应的对象*/
            HttpServletResponse response) throws IOException {
        // 1、判断当前请求的类型
        boolean judgeRequestType = CrowdUtil.judgeRequestType(request);
        logger.info("judgeRequestType:"+judgeRequestType);
        // 2、如果是Ajax请求
        if (judgeRequestType){
            // 3、创建ResultEntity对象
            ResultEntity<Object> resultEntity = ResultEntity.failed(exception.getMessage());
            // 4、创建 Gson 对象
            Gson gson = new Gson();
            // 5、ResultEntity对象转化成JSON字符串
            String toJson = gson.toJson(resultEntity);
            // 6、将JSON字符串最为响应体返回给浏览器
            response.getWriter().write(toJson);
            logger.info("toJson:"+toJson);
            // 7、上面已经进行了原生的response对象返回了相应对象，所有不提供ModelAndView对象
            return null;
        }
        // 8、如果不是Ajax请求则创建ModelAndView对象
        ModelAndView modelAndView = new ModelAndView();
        // 9、将Exception对象存入模型
        modelAndView.addObject(CrowdConstant.ATTR_NAME_EXCEPTION,exception);
        // 10、设置对应的视图
        modelAndView.setViewName(viewName);
        // 11、返回ModelAndView对象
        return modelAndView;
    }

}
